package cn.ecnu.note.service.impl;

import cn.ecnu.common.Constant;
import cn.ecnu.common.Permission;
import cn.ecnu.exception.RRXException;
import cn.ecnu.note.feign.SearchServiceFeign;
import cn.ecnu.note.mapper.NoteMapper;
import cn.ecnu.note.pojo.Note;
import cn.ecnu.note.service.NoteService;
import cn.ecnu.note.vo.NoteFrontVo;
import cn.ecnu.note.vo.NoteVo;
import cn.ecnu.note.vo.ViewNoteVo;
import cn.ecnu.utils.PaginationUtil;
import cn.ecnu.vo.common.Pagination;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

@Slf4j
@Service
public class NoteServiceImpl implements NoteService {

    @Resource
    private NoteMapper noteMapper;

    @Autowired
    private ExecutorService executor;

    @Autowired
    private SearchServiceFeign searchServiceFeign;

    @Override
    public NoteVo addNote(NoteFrontVo vo) {
        Note note = new Note();
        BeanUtils.copyProperties(vo, note); // Copy Vo
        note.setFlag(1); // 设置为可见
        noteMapper.insertNote(note);
        CompletableFuture.runAsync(() -> {
            searchServiceFeign.changeNoteNum(vo.getPaperId(), 1);
        }, executor);
        return noteMapper.getNoteVoById(note.getNoteId());
    }

    @Override
    public int deleteNoteById(Integer noteId, Integer userId, Integer permission) {
        Note note = noteMapper.getNoteById(noteId);
        if (note == null) throw new RRXException(Constant.NO_RESOURCE.getMsg(), Constant.NO_RESOURCE.getCode());
        if (NumberUtils.compare(userId, note.getUserId()) != 0 && !Permission.isAdmin(permission))
            throw new RRXException(Constant.NO_PERMISSION.getMsg(), Constant.NO_PERMISSION.getCode());

        // 最终删除
        CompletableFuture.runAsync(() -> {
            searchServiceFeign.changeNoteNum(note.getPaperId(), -1);
        }, executor);
        return noteMapper.deleteNoteById(noteId);
    }

    @Override
    public ViewNoteVo getNoteByPaperId(Integer paperId, Integer pageNum) {
        int pageSize = 2;
        int totalSize = noteMapper.getNoteCountByPaperId(paperId);
        Pagination pagination = PaginationUtil.paging(pageNum, totalSize, pageSize, "/node/getNoteByPaperId/" + paperId);
        pageNum = pagination.getCurrentPage();

        ViewNoteVo vo = new ViewNoteVo();
        vo.setPagination(pagination);
        List<NoteVo> notes = noteMapper.getNoteByPaperId(paperId, (pageNum - 1) * pageSize, pageSize);
        vo.setNotes(notes);
        return vo;
    }

    @Override
    public ViewNoteVo getNoteByUserId(Integer userId, Integer pageNum) {
        int pageSize = 2;
        int totalSize = noteMapper.getNoteCountByUserId(userId);
        Pagination pagination = PaginationUtil.paging(pageNum, totalSize, pageSize, "/node/getNoteByUserId/" + userId);
        pageNum = pagination.getCurrentPage();
        ViewNoteVo vo = new ViewNoteVo();
        vo.setPagination(pagination);
        List<NoteVo> notes = noteMapper.getNoteByUserId(userId, (pageNum - 1) * pageSize, pageSize);
        vo.setNotes(notes);
        return vo;
    }

    @Override
    public int updateNoteById(NoteFrontVo vo, Integer userId, Integer permission) {
        if (vo.getNoteId() == null) throw new RRXException(Constant.ARGUMENT_INVALID.getMsg(), Constant.ARGUMENT_INVALID.getCode());
        Note note = noteMapper.getNoteById(vo.getNoteId());
        if (note == null) throw new RRXException(Constant.NO_RESOURCE.getMsg(), Constant.NO_RESOURCE.getCode());
        if (NumberUtils.compare(userId, note.getUserId()) != 0 && !Permission.isAdmin(permission))
            throw new RRXException(Constant.NO_PERMISSION.getMsg(), Constant.NO_PERMISSION.getCode());
        BeanUtils.copyProperties(vo, note);
        return noteMapper.updateNoteById(note);
    }

    @Override
    public NoteVo getNoteByNoteId(Integer noteId) {
        return noteMapper.getNoteByNoteId(noteId);
    }
}
